/* 帧缓冲 */
class FrameBuffer{
	constructor(gl, size={}, opt={}){
		const {width=1, height=1} = size;
		const {
			colorAttach=true,
			depthAttach=false
		} = opt;
		this.gl = gl;
		this.size = size;
		
		//创建FBO
		const fbo = gl.createFramebuffer();
		this.object = fbo;
		
		this.bindSafe(()=>{
			//附加纹理为第一个颜色附件
			if (colorAttach){
				if (colorAttach === true){ //自行创建纹理
					this.colorTexture = new Texture2D(gl, null, size, {
						internalFormat: gl.RGBA,
						format: gl.RGBA,
						dataType: gl.UNSIGNED_BYTE,
						reduce: gl.LINEAR,
						wrapX: gl.REPEAT,
						wrapY: gl.REPEAT
					});
				}else{ //指定纹理
					this.colorTexture = colorAttach;
				}
				
				gl.framebufferTexture2D(
					gl.FRAMEBUFFER,
					gl.COLOR_ATTACHMENT0,
					gl.TEXTURE_2D,
					this.colorTexture.texture,
					0 //level
				);
			}
			
			//深度缓冲
			if (depthAttach){
				if (depthAttach === true){ //自行创建纹理
					this.depthTexture = new Texture2D(gl, null, size, {
						internalFormat: gl.DEPTH_COMPONENT24,
						format: gl.DEPTH_COMPONENT,
						dataType: gl.UNSIGNED_INT,
						reduce: gl.LINEAR,
						wrapX: gl.REPEAT,
						wrapY: gl.REPEAT
					});
				}else{ //指定纹理
					this.depthTexture = depthAttach;
				}
				
				gl.framebufferTexture2D(
					gl.FRAMEBUFFER,
					gl.DEPTH_ATTACHMENT,
					gl.TEXTURE_2D,
					this.depthTexture.texture,
					0 //level
				);
			}
		});
	}
	
	//绑定
	bind(){
		this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.object);
		this.gl.viewport(0, 0, this.size.width, this.size.height);
		return this;
	}
	
	//解绑
	unbind(){
		this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
		return this;
	}
	
	//安全绑定
	bindSafe(func){
		//保存状态
		const bindingFramebuffer = this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING);
		const settingViewport = this.gl.getParameter(this.gl.VIEWPORT);
		//改变状态
		this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.object);
		this.gl.viewport(0, 0, this.size.width, this.size.height);
		func();
		//恢复状态
		this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, bindingFramebuffer);
		this.gl.viewport(...settingViewport);
		return this;
	}
	
	//重调大小
	resize(width, height){
		this.size.width = width;
		this.size.height = height;
		if (this.colorTexture){
			this.colorTexture.size.width = width;
			this.colorTexture.size.height = height;
			this.colorTexture.update();
		}
		if (this.depthTexture){
			this.depthTexture.size.width = width;
			this.depthTexture.size.height = height;
			this.depthTexture.update();
		}
	}
}
